module recv_data_buf
  #(
     parameter  SYNC1=10'b1010_1010_10,
     parameter  SYNC2=10'b1010_1010_11
   )
   (
     input					rst,
     input					clk_100M,
     input					clk_400M,
     input					rx,
     input					rx_nce,   //chip select
     input					rx_noe,   // output enable
     input					rx_nwe,   //write enable
     output	reg		rx_rdy,	//data ready
     input			[9:0]	rx_addr, //address
     output	reg[15:0]rx_data,  //received data output to CPU interface
     input			[15:0]rx_we_data
   );

  reg  				rx_nce_r;
  reg  				nrx_nce_r;
  reg  				rx_noe_r;
  reg  				nrx_noe_r;
  reg  				nnrx_noe_r;  //
  reg				rx_noe_fg;   //falling edge

  reg         	rx_nwe_r;
  reg         	nrx_nwe_r;
  reg         	nnrx_nwe_r;
  reg         	rx_nwe_fg;   //falling edge

  reg	[15:0]	rx_we_data_r;

  wire	[15:0] 	rx_data_tmpa;

  reg  [9:0]		rx_addr_r;

  always@(posedge clk_100M or posedge rst)
    if(rst)
    begin
      rx_nce_r		<=1'b1;
      nrx_nce_r	<=1'b0;
      rx_noe_r		<=1'b1;
      nrx_noe_r	<=1'b0;
      nnrx_noe_r	<=1'b1;
      rx_noe_fg	<=1'b0;

      rx_nwe_r		<=1'b1;
      nrx_nwe_r	<=1'b0;
      nnrx_nwe_r	<=1'b1;
      rx_nwe_fg	<=1'b0;
      rx_addr_r	<=255;
      rx_data		<=0;
      rx_we_data_r<=0;
      rx_rdy		<=1'b1;
    end
    else
    begin
      rx_nce_r		<=rx_nce;
      nrx_nce_r	<=~rx_nce_r;

      rx_noe_r		<=rx_noe;
      nrx_noe_r	<=~rx_noe_r;
      nnrx_noe_r	<=~nrx_noe_r;
      rx_noe_fg	<=nrx_noe_r&nnrx_noe_r;

      rx_nwe_r		<=rx_nwe;
      nrx_nwe_r	<=~rx_nwe_r;
      nnrx_nwe_r	<=~nrx_nwe_r;
      rx_nwe_fg	<=nrx_nwe_r&nnrx_nwe_r;
      rx_addr_r	<=rx_addr;

      rx_we_data_r<=rx_we_data;

      rx_rdy		<=1'b1;

      if(rx_noe_fg&nrx_nce_r)
        rx_data<=rx_data_tmpa ;
    end

  wire         rx_data_en;
  wire			 ko;
  wire	[7:0]  rx_data_8b10b;

  reg   [15:0] rv_data_bufb;  // received data to buf b
  reg	[9:0]  rv_lenb;
  reg	[8:0]  rv_addr_br;   //receive address  registered on buf b side
  reg			 rv_addr_tb;// toggle b
  reg			 rv_web;
  wire	[15:0] data_from_bufb;//read from buffer b port

  wire [9:0]  rv_addrb={rv_addr_tb,rv_addr_br};

  reg	[2:0] rvb_st;

  always@(posedge clk_100M or posedge rst)
    if(rst)
    begin
      rv_data_bufb<=15'b0;
      rv_lenb		<=10'b0;
      rv_addr_br	<=9'd511;
      rv_addr_tb	<=1'b0;
      rv_web		<=1'b0;
      rvb_st		<=3'b0;
    end
    else
    case(rvb_st)
      0:
      begin
        rv_data_bufb<=15'b0;
        rv_lenb		<=10'b0;
        rv_addr_br	<=9'd511;
        rv_addr_tb	<=1'b0;
        rv_web		<=1'b0;
        rvb_st		<=3'b1;
      end
      1:
      begin
        rv_data_bufb<=15'b0;
        rv_lenb		<=10'b0;
        rvb_st		<=2;
      end
      2:
      begin
        if(data_from_bufb[15])
        begin
          rv_addr_tb	<=~rv_addr_tb;
          rvb_st		<=1;
        end
        else
          rvb_st		<=3;
      end
      3:
      begin
        if(rx_data_en)
        begin
          if((ko ==1'b1)&&(rx_data_8b10b==8'hbc)) //strat of frame
            rvb_st		<=4;
        end
        else
          rvb_st		<=3;
      end
      4:
      begin
        rv_web		<=1'b0;
        if(rx_data_en)
        begin
          // rv_addr_br	<=rv_addr_br+1'b1;
          // rv_web		<=1'b1;
          rv_data_bufb[7:0]<=rx_data_8b10b;

          if((rx_data_8b10b==8'h3c)&&(ko==1'b1))
          begin  //waiting for K28.1
            rvb_st		<=6;
          end
          else
          begin
            rv_lenb		<= rv_lenb+1'b1;
            rvb_st		<=5;
          end
        end
      end
      5:
      begin
        rv_web		<=1'b0;
        if(rx_data_en)
        begin
          rv_data_bufb[15:8]<=rx_data_8b10b;
          rv_web		<=1'b1;

          if((rx_data_8b10b==8'h3c)&&(ko==1'b1))
          begin  //k28.1
            rv_data_bufb[15:8]<=8'b0;
            rvb_st		<=6;
          end
          else
          begin
            rv_lenb		<= rv_lenb+1'b1;
            rv_addr_br	<=rv_addr_br+1'b1;
            rvb_st		<=4;
          end
        end
      end
      6:
      begin
        rv_web		<=1'b1;
        rv_addr_br	<=511;
        rv_data_bufb<={1'b1,5'b0,rv_lenb};
        rvb_st		<=7;
      end
      7:
      begin
        rv_web		<=1'b0;
        rv_addr_br	<=511;
        rv_addr_tb	<=~rv_addr_tb;
        rvb_st		<=1;
      end
      default:
        rvb_st		<=3'b0;
    endcase

  rx_data_buf	rx_data_buf_inst
              (
                .address_a 	(rx_addr_r ),
                .address_b 	(rv_addrb ),
                .clock_a 	(clk_100M ),
                .clock_b 	(clk_100M ),
                .data_a 		(rx_we_data_r),
                .data_b 		(rv_data_bufb ),
                .wren_a 		(rx_nwe_fg ),
                .wren_b 		(rv_web ),
                .q_a 			(rx_data_tmpa ),
                .q_b 			(data_from_bufb )

              );
			  
  recv_data
    #(
      .SYNC1	(SYNC1),
      .SYNC2	(SYNC2)
    )
    recv_data_inst
    (
      .rst					(rst),
      .clk_100M			(clk_100M),
      .clk_400M			(clk_400M),
      .rx					(rx),
      .ko_100Mr			(ko),
      .rx_data_8b10b_r	(rx_data_8b10b),
      .rx_data_en_100Mrr(rx_data_en)
    );

endmodule

